hack.forms = {}

hack.forms.button = {
	x = 0,
	y = 0,
	w = 64,
	h = 18,
	label = "Button",
	align = 1,
	font = "Trebuchet18",
	b = 4,
	enabled = true,
	draw = true,
	drawonly = nil,
	color1 = hack.scheme.c1,
	color2 = hack.scheme.c3,
	color3 = hack.scheme.c4,
	colorf = hack.scheme.f1,
	color1d = hack.scheme.c1,
	color2d = hack.scheme.c3,
	color3d = hack.scheme.c1,
	colorfd = hack.scheme.f5,
	draw = function(self,window,name,comp)
		if not self.drawonly then
			local s = hack.scheme
			local col = self.color1
			local ret = nil
			local colx = ""
			if not self.enabled then
				colx = "d"
			end
			
			if hack.focus[1] == window.key and
				hack.focus[2] == (self.parent or "") and
				window.mx > self.x and
				window.mx < self.x+self.w and
				window.my > self.y and
				window.my < self.y+self.h
			then
				col = self["color2"..colx]
				ret = 0
				
				if comp.mc[0].click == 1 then
					comp.mc[0].click = 2
					comp.mc[0].uid = window.uid
					comp.mc[0].data = {
						type = "button",
						name = name,
						}
					if self.enabled then
						ret = 1
					end
					col = self["color3"..colx]
				elseif comp.mc[0].click == 2 and
					comp.mc[0].uid == window.uid and
					comp.mc[0].data.type == "button" and
					comp.mc[0].data.name == name
				then
					ret = 2
					col = self["color3"..colx]
				elseif comp.mc[0].click == -1 and
					comp.mc[0].uid == window.uid and
					comp.mc[0].data.type == "button" and
					comp.mc[0].data.name == name
				then
					if self.enabled then
						ret = -1
					end
					comp.mc[0].click = 0
					comp.mc[0].uid = nil
					comp.mc[0].data = nil
				end
			end
			
			if self.forceret and self.forceret ~= ret then
				col = self.forceretcolor
			end
			
			local xpos
			if self.align == 1 then
				xpos = self.w*.5
			elseif self.align == 0 then
				xpos = self.b
			elseif self.align == 2 then
				xpos = self.w-self.b
			end
			
			if self.draw then
				window:DrawRoundedRect(self.x+self.b,self.y+self.b,self.w-self.b*2,self.h-self.b*2,self.b,col,true)
				window:DrawText(self.label,self.font,self.x+xpos,self.y,self["colorf"..colx],self.align)
				
				return self.forceret or ret
			else
				return {
					self.forceret or ret,
					{self.x+self.b,self.y+self.b,self.w-self.b*2,self.h-self.b*2,self.b,col,true},
					{self.label,self.font,self.x+xpos,self.y,self["colorf"..colx],self.align},
				}
			end
		else
			window:DrawRoundedRect(unpack(self.drawonly[2]))
			window:DrawText(unpack(self.drawonly[3]))
			return self.drawonly[1]
		end
		/*
		Example of pre-collision determination usage:
		
		//Assume table button = {args here}
		
		local newIn = self:DrawForm(button.label,"button",button)
		
		//Other drawings and stuff here
		
		button.draw = nil
		button.drawonly = newIn
		newIn = self:DrawForm(button.label,"button",button)
		button.drawonly = nil
		*/
	end,
	}

hack.forms.edit = {
	x = 0,
	y = 0,
	w = 64,
	h = 24,
	lines = 0, //0 for math.floor(h/24) lines (Automatic), higher for fixed number
	multiline = 0, //0 for single line, 1 for maximum of lines, 2 for scroll
	curline = 1,
	wrap = 0,
	text = "",
	align = 0,
	font = "Trebuchet18",
	b = 4,
	enabled = true,
	draw = true,
	drawonly = nil,
	color1 = hack.scheme.c6,
	color2 = hack.scheme.c1,
	color3 = hack.scheme.c4,
	colorf = hack.scheme.f6,
	color1d = hack.scheme.c6,
	color2d = hack.scheme.c1,
	color3d = hack.scheme.c1,
	colorfd = hack.scheme.f6,
	draw = function(self,window,name,comp)
		local extext = function(text)
			
			local tble={}
			local ll=1
			while true do
				local l=string.find(text,"\n",ll,true)
				if l~=nil then
					table.insert(tble,string.sub(text,ll,l-1)) 
					ll=l+1
				else
					table.insert(tble,string.sub(text,ll))
					break
				end
			end
			
			return tble
		end
		
		if not window[name] then //Allocate memory space
			window[name] = {text = self.text,cursor={x=0,y=1}}
		end
		
		if not self.drawonly then
			if self.lines < 1 then
				self.lines = math.floor(self.h/24)
			end
			local temp,lines = string.gsub(window[name].text,"\n","\n")
			
			local s = hack.scheme
			local col = self.color1
			local ret = nil
			local colx = ""
			if not self.enabled then
				colx = "d"
			end
			
			local updcursor
			
			if comp.key.focus ~= window.uid then
				if hack.focus[1] == window.key and
					hack.focus[2] == (self.parent or "") and
					window.mx > self.x and
					window.mx < self.x+self.w and
					window.my > self.y and
					window.my < self.y+self.h
				then
					col = self["color2"..colx]
					ret = 0
					
					if comp.mc[0].click == 1 then
						comp.mc[0].click = 2
						comp.mc[0].uid = window.uid
						comp.mc[0].data = {
							type = "button",
							name = name,
							}
						if self.enabled then
							ret = 1
						end
						col = self["color3"..colx]
					elseif comp.mc[0].click == 2 and
						comp.mc[0].uid == window.uid and
						comp.mc[0].data.type == "button" and
						comp.mc[0].data.name == name
					then
						ret = 2
						col = self["color3"..colx]
					elseif comp.mc[0].click == -1 and
						comp.mc[0].uid == window.uid and
						comp.mc[0].data.type == "button" and
						comp.mc[0].data.name == name
					then
						if self.enabled then
							ret = -1
						end
						comp.mc[0].click = 0
						comp.mc[0].uid = nil
						comp.mc[0].data = nil
					end
				end
			elseif hack.focus[1] == window.key and
				hack.focus[2] == (self.parent or "") and
				window.mx > self.x and
				window.mx < self.x+self.w and
				window.my > self.y and
				window.my < self.y+self.h
			then
				if comp.mc[0].click == 1 then
					comp.mc[0].click = 2
					comp.mc[0].uid = window.uid
					comp.mc[0].data = {
						type = "cursor",
						name = name,
					}
				elseif comp.mc[0].click == -1 and
					comp.mc[0].uid == window.uid and
					comp.mc[0].data.type == "cursor" and
					comp.mc[0].data.name == name
				then
					if self.enabled then
						updcursor = true
					end
				end
			end
			
			if self.forceret and self.forceret ~= ret then
				col = self.forceretcolor
			end
			
			local xpos
			if self.align == 1 then
				xpos = self.w*.5
			elseif self.align == 0 then
				xpos = self.b
			elseif self.align == 2 then
				xpos = self.w-self.b
			end
			
			if hack.focus[1] == window.key and comp.key.focus == window.uid and comp.key.key then
				window[name].text = tostring(self:processkey(window,name,window[name].text,comp.key.key,window[name].cursor))
				comp.key.key = nil
				comp.key.mod = {}
			end
			
			local SetCursorPos = function(cx,cy)
				local text = extext(window[name].text)
				
				surface.SetFont(self.font)
				local px,py = surface.GetTextSize(string.sub(text[1],1,1))
				window[name].cursor = {
					x = math.Round(cx/px),
					y = math.Round(cy/(py)),
				}
				//Ambiguous number 6
				
				if window[name].cursor.y > #text then
					window[name].cursor.y = #text
				elseif window[name].cursor.y < 1 then
					window[name].cursor.y = 1
				end
				
				local len = #tostring(text[window[name].cursor.y] or "")
				if len < window[name].cursor.x then
					window[name].cursor.x = len
				end
				
				//Begin corrections
				local last = nil
				local lastc = window[name].cursor.x
				for i=1,1000 do
					local px = surface.GetTextSize(string.sub(text[window[name].cursor.y],1,window[name].cursor.x))
					if px == cx then
						break
					elseif last and last < cx and px > cx then
						if math.abs(last-cx) < math.abs(px-cx) then
							window[name].cursor.x = lastc
						end
						break
					elseif px < cx then
						window[name].cursor.x = window[name].cursor.x + 1
					else
						window[name].cursor.x = window[name].cursor.x - 1
					end
					
					last = px
					lastc = window[name].cursor.x
					
					local len = #tostring(text[window[name].cursor.y] or "")
					if len < window[name].cursor.x - 1 then
						window[name].cursor.x = len + 1
						break
					end
				end
				if window[name].cursor.x > 0 then
					window[name].cursor.x = window[name].cursor.x - 1
				end
			end
			
			if ret == -1 or updcursor then
				comp.key.focus = window.uid
				local text = extext(window[name].text)
				
				if #window[name].text > 0 then
					comp.key.last = CurTime()
					local cx = window.mx-self.x
					local cy = window.my-self.y+self.b+6
					
					SetCursorPos(cx,cy)
				end
			end
			
			if self.draw then
				window:DrawRoundedRect(self.x+self.b,self.y+self.b,self.w-self.b*2,self.h-self.b*2,self.b,col,true)
				window:DrawText(window[name].text,self.font,self.x+xpos,self.y,self["colorf"..colx],self.align)
				
				if hack.focus[1] == window.key and comp.key.focus == window.uid and (CurTime()-comp.key.last)%1 < .5 then
					//Warning: SetFont is not called because text was drawn, if text is not drawn, add SetFont.
					local text = extext(window[name].text)
					local tw,th = surface.GetTextSize(string.sub(text[window[name].cursor.y] or " ",1,window[name].cursor.x))
					
					//Ambiguous number 6
					window:DrawRect(self.x+self.b+tw,self.y+self.b+(window[name].cursor.y-1)*th,4,th-6,hack.scheme.f6)
				end
				return self.forceret or ret
			else
				return {
					self.forceret or ret,
					{self.x+self.b,self.y+self.b,self.w-self.b*2,self.h-self.b*2,self.b,col,true},
					{window[name].text,self.font,self.x+xpos,self.y,self["colorf"..colx],self.align},
				}
			end
		else
			window:DrawRoundedRect(unpack(self.drawonly[2]))
			window:DrawText(unpack(self.drawonly[3]))
			return self.drawonly[1]
		end
	end,
	GetText = function(self,window,name,comp)
		return window[name].text
	end,
	processkey = function(self,window,name,text,key,cursor)
		local extext = function(text)
			
			local tble={}
			local ll=1
			while true do
				local l=string.find(text,"\n",ll,true)
				if l~=nil then
					table.insert(tble,string.sub(text,ll,l-1)) 
					ll=l+1
				else
					table.insert(tble,string.sub(text,ll))
					break
				end
			end
			
			return tble
		end
		
		local pos = 1
		if window[name].cursor.y > 1 then
			for i=1,window[name].cursor.y-1 do
				pos = string.find(text,"\n",pos)+1
			end
		end
		pos = pos + window[name].cursor.x - 1
		
		key = tostring(key)
		if key == "backspace" then
			if pos > 0 then
				if string.sub(text,pos,pos) ~= "\n" then
					window[name].cursor.x = window[name].cursor.x-1
				else
					window[name].cursor.y = window[name].cursor.y-1
					window[name].cursor.x = #extext(text)[window[name].cursor.y]
				end
				return string.sub(text,1,pos-1)..string.sub(text,pos+1)
			else
				return text
			end
		elseif key == "delete" then
			if pos < #text then
				return string.sub(text,1,pos)..string.sub(text,pos+2)
			else
				return text
			end
		elseif key == "\n" then
			local temp,search = string.gsub(text,"\n","\n")
			if self.multiline == 2 then
				window[name].cursor.y = window[name].cursor.y+1
				
				window[name].cursor.x = 0
				return string.sub(text,1,pos)..key..string.sub(text,pos+1)
			elseif self.multiline == 1 and self.lines > search+1 then
				window[name].cursor.y = window[name].cursor.y+1
				
				window[name].cursor.x = 0
				return string.sub(text,1,pos)..key..string.sub(text,pos+1)
			else
				return text
			end
		elseif #key == 1 then
			window[name].cursor.x = window[name].cursor.x+1
			return string.sub(text,1,pos)..key..string.sub(text,pos+1)
		elseif #key == 2 and string.sub(key,1,1) == "d" then
			({
				dU = function()
					local text = extext(window[name].text)
					if window[name].cursor.y > 1 then
						window[name].cursor.y = window[name].cursor.y-1
					else
						window[name].cursor.x = 0
					end
					
					local len = #tostring(text[window[name].cursor.y] or "")
					if len < window[name].cursor.x then
						window[name].cursor.x = len
					end
				end,
				dD = function()
					local text = extext(window[name].text)
					local len = #tostring(text[window[name].cursor.y] or "")
					if #text > window[name].cursor.y then
						window[name].cursor.y = window[name].cursor.y+1
					else
						window[name].cursor.x = len
					end
					
					local len = #tostring(text[window[name].cursor.y] or "")
					if len < window[name].cursor.x then
						window[name].cursor.x = len
					end
				end,
				dL = function()
					if window[name].cursor.x > 0 then
						window[name].cursor.x = window[name].cursor.x-1
					end
				end,
				dR = function()
					local text = extext(window[name].text)
					if #tostring(text[window[name].cursor.y] or "") > window[name].cursor.x then
						window[name].cursor.x = window[name].cursor.x+1
					end
				end,
			})[key]()
			return text
		else
			return text
		end
	end,
	}
hack.macros = {}
hack.macros.contextmenu = {
	x = 0,
	y = 0,
	w = 128,
	h = 128,
	mid = 0,
	items = {
		{
			label = "Enabled",
			enabled = true,
		},
		{
			label = "Disabled",
			enabled = false,
		},
		{
			label = "List",
			enabled = true,
			list = true,
			[1] = {
				label = "Enabled",
				enabled = true,
			},
			[2] = {
				label = "Disabled",
				enabled = false,
			},
		},
	},
	draw = function(self,window,name,comp)
		if not window[name..self.mid] then //Allocate memory space
			window[name..self.mid] = {}
		end
		
		local s = hack.scheme
		local bounds = {
			self.x,
			self.y,
			self.w,
			#self.items*18+8,
		}
		window:DrawRoundedRect(bounds[1]+8,bounds[2]+8,bounds[3]-16,bounds[4]-16,8,s.c2,true)
		if window.macrobounds then
			table.insert(window.macrobounds,{
				window.x+bounds[1],
				window.y+bounds[2],
				window.x+bounds[1]+bounds[3],
				window.y+bounds[2]+bounds[4],
				name..self.mid,
			})
		else
			window.macrobounds = {
				{
					window.x+bounds[1],
					window.y+bounds[2],
					window.x+bounds[1]+bounds[3],
					window.y+bounds[2]+bounds[4],
					name..self.mid,
				},
			}
		end
		
		local button = {
			x = self.x+4,
			y = self.y+4,
			w = self.w-8,
			align = 0,
			color1 = Color(0,0,0,0),
			enabled = true,
			parent = (name..self.mid),
		}
		local ret = {}
		
		for k,v in ipairs(self.items) do
			if not v.list then
				button.label = v.label
				button.y = self.y+(k-1)*18+4
				
				if not v.enabled then
					button.enabled = false
				end
				
				local sret = window:DrawForm(k..self.mid,"button",button)
				if v.enabled then
					if sret == -1 then
						ret = {k}
					elseif sret == 0 then
						window[name..self.mid].lastlight = k
						ret = {false,k}
					end
				end
			else
				button.label = v.label
				button.y = self.y+(k-1)*18+4
				
				if not v.enabled then
					button.enabled = false
				end
				
				if window[name..self.mid].lastlight == k then
					button.forceretcolor = s.c1
					button.forceret = 0
				end
				
				if window:DrawForm(k,"button",button) == 0 or button.forceret then
					window[name..self.mid].lastlight = k
					
					if v.enabled then
						local args = {}
						args.x = self.x+self.w
						args.y = self.y+(k-1)*18
						args.w = v.w
						args.h = v.h
						args.mid = self.mid+1
						args.draw = v.draw
						args.items = v
						
						ret = {k}
						for i,o in ipairs(window:DrawMacro(name..(self.mid+1),"contextmenu",args)) do
							table.insert(ret,o)
						end
					end
				end
			end
			
			button.forceretcolor = nil
			button.forceret = nil
			button.enabled = true
		end
		
		return ret
	end,
	}









































